package com.znjc.device.service;

import com.znjc.common.constant.DeviceConstants;
import com.znjc.device.domain.IotSerial;
import com.znjc.device.websocket.WebSocketUsers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

/**
 * 定时任务调度服务
 * 负责动态管理采集任务的调度
 */
@Slf4j
@Service
public class TaskSchedulerService {

    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;

    @Autowired
    private SerialPortService serialPortService;

    @Autowired
    private DataCollectorService dataCollectorService;

    // 存储正在运行的任务
    private final Map<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();

    /**
     * 启动采集任务
     *
     * @param iotSerial 串口配置
     * @return 是否启动成功
     */
    public boolean startCollectionTask(IotSerial iotSerial) {
        String portKey = iotSerial.getSerialCode();

        try {
            // 检查是否已有任务在运行
            if (scheduledTasks.containsKey(portKey)) {
                log.warn("串口 {} 的采集任务已在运行", portKey);
                WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"串口 "+portKey+" 的采集任务已在运行");
                return false;
            }

            // 1. 打开串口
            if (!serialPortService.openSerialPort(iotSerial)) {
                log.error("打开串口失败，无法启动采集任务");
                WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"打开串口失败，无法启动采集任务");
                return false;
            }

            // 2. 创建定时任务
            ScheduledFuture<?> future = taskScheduler.schedule(
                    () -> executeTimedCollection(iotSerial),
                    new CronTrigger(iotSerial.getGatherTime())
            );

            scheduledTasks.put(portKey, future);
            log.info("串口 {} 采集任务启动成功，cron表达式: {}", portKey, iotSerial.getGatherTime());
            WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"串口 "+portKey+" 采集任务启动成功，cron表达式: "+iotSerial.getGatherTime());

            return true;

        } catch (Exception e) {
            log.error("启动采集任务异常: {}", e.getMessage(), e);
            WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"启动采集任务异常: {}"+e.getMessage());
            // 如果启动失败，关闭串口
            serialPortService.closeSerialPort();
            return false;
        }
    }

    /**
     * 停止采集任务
     *
     * @param serialCode 串口号
     * @return 是否停止成功
     */
    public boolean stopCollectionTask(String serialCode) {
        try {
            ScheduledFuture<?> future = scheduledTasks.get(serialCode);

            if (future != null) {
                // 取消定时任务
                future.cancel(true);
                scheduledTasks.remove(serialCode);

                // 关闭串口
                serialPortService.closeSerialPort();

                log.info("串口 {} 采集任务已停止", serialCode);
                WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"串口 "+serialCode+" 采集任务已停止");
                return true;
            } else {
                log.warn("串口 {} 没有正在运行的采集任务", serialCode);
                WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"串口 "+serialCode+" 没有正在运行的采集任务");
                return false;
            }

        } catch (Exception e) {
            WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"停止采集任务异常: {}"+e.getMessage());
            return false;
        }
    }

    /**
     * 执行定时采集
     */
    private void executeTimedCollection(IotSerial iotSerial) {
        try {
            // 检查串口是否仍然打开
            if (!serialPortService.isPortOpen()) {
                log.error("串口未打开，无法执行采集任务");
                WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"串口未打开，无法执行采集任务");
                stopCollectionTask(iotSerial.getSerialCode());
                return;
            }

            log.debug("执行定时采集，串口: {}", iotSerial.getSerialCode());
            WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"执行定时采集，串口: {}"+iotSerial.getSerialCode());

            // 异步执行采集任务
            dataCollectorService.executeCollectionTask(iotSerial)
                    .exceptionally(throwable -> {
                        log.error("采集任务执行异常: {}", throwable.getMessage(), throwable);
                        WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"采集任务执行异常: {}"+throwable.getMessage());
                        return false;
                    });

        } catch (Exception e) {
            log.error("定时采集执行异常: {}", e.getMessage(), e);
            WebSocketUsers.sendMessageToUserByText(DeviceConstants.VUE_MSG_CLINET_9996,"定时采集执行异常: {}"+e.getMessage());
        }
    }

    /**
     * 检查任务是否在运行
     */
    public boolean isTaskRunning(String serialCode) {
        return scheduledTasks.containsKey(serialCode);
    }
}